package com.aji.service.impl;

import com.aji.config.FileEnvIsotopeConfig;
import com.aji.dto.IsotopeAddDto;
import com.aji.dto.IsotopeChangeDto;
import com.aji.dto.IsotopeDto;
import com.aji.entity.*;
import com.aji.mapper.IsotopeMapper;
import com.aji.mapper.LocMapper;
import com.aji.mapper.ModelMapper;
import com.aji.result.PageResult;
import com.aji.service.IsotopeService;
import com.aji.utills.CsvUtills;
import com.aji.vo.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.opencsv.bean.CsvToBeanBuilder;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class IsotopeSeviceImpl implements IsotopeService {
    @Autowired
    IsotopeMapper isotopeMapper;

    @Autowired
    FileEnvIsotopeConfig fileEnvIsotopeConfig;

    @Autowired
    ModelMapper modelMapper;

    @Autowired
    LocMapper locMapper;
    @Override
    public PageResult pageQuery(IsotopeDto isotopeDto,int page1,int pageSize) {
        PageHelper.startPage(page1,pageSize);
        List<IsotopeVo> isotopeVoList = isotopeMapper.pageQuery(isotopeDto);
        Page<IsotopeVo> page = (Page<IsotopeVo>) isotopeVoList;
        long total=page.getTotal();
        List<IsotopeVo>records=page.getResult();
        return new PageResult(total,records);
    }

    @Override
    public void deleteByIds(List<Integer> ids) {
        isotopeMapper.deleteByIds(ids);
        isotopeMapper.deleteContentsByIds(ids);
        isotopeMapper.deleteOriginByIds(ids);
    }

    @Override
    public void add(IsotopeAddDto isotopeAddDto) {
        LocalDateTime createTime = LocalDateTime.now();
        Isotope isotope = Isotope.builder()
                .se(isotopeAddDto.getSe())
                .a(isotopeAddDto.getA())
                .recId(isotopeAddDto.getRecId())
                .locId(isotopeAddDto.getLocId())
                .typeId(isotopeAddDto.getTypeId())
                .createTime(createTime)
                .batchId(isotopeAddDto.getBatchId())
                .build();

        isotopeMapper.add(isotope);
        Integer isoId = isotopeMapper.getLastInsertId(); // 假设此方法返回 LAST_INSERT_ID()
        isotope.setId(isoId);

        // 使用获取的 ID
        IsotopeMore isotopeMore = IsotopeMore.builder()
                .isoId(isotope.getId())
                .contents(isotopeAddDto.getContents())
                .build();
        isotopeMapper.addMore(isotopeMore);

        IsotopeOrigin isotopeOrigin = IsotopeOrigin.builder()
                .isotopeId(isotope.getId())
                .originId(isotopeAddDto.getOriginId())
                .build();
        isotopeMapper.addMore1(isotopeOrigin);

    }

    @Override
    public void upDate(IsotopeChangeDto isotopeChangeDto,int id) {
        LocalDateTime changeTime =  LocalDateTime.now();
        Isotope isotope = Isotope.builder()
                .id(id)
                .se(isotopeChangeDto.getSe())
                .a(isotopeChangeDto.getA())
                .recId(isotopeChangeDto.getRecId())
                .locId(isotopeChangeDto.getLocId())
                .typeId(isotopeChangeDto.getTypeId())
                .changeTime(changeTime)
                .batchId(isotopeChangeDto.getBatchId()).build();
        isotopeMapper.upDate(isotope);

        IsotopeMore isotopeMore = IsotopeMore.builder()
                .isoId(id)
                .contents(isotopeChangeDto.getContents()).build();
        isotopeMapper.updateMore(isotopeMore);

        IsotopeOrigin isotopeOrigin = IsotopeOrigin.builder()
                .originId(isotopeChangeDto.getOriginId())
                .isotopeId(id)
                .build();
        isotopeMapper.updateMore1(isotopeOrigin);
    }

    @Override
    public IsotopeByIdVo selectById(int id) {
        return isotopeMapper.selectById(id);
    }

    @Override
    public List<IsotopeVo> selectCon(IsotopeDto isotopeDto) {
        return isotopeMapper.pageQuery(isotopeDto);
    }

    @Override
    public void trainIso(List<Integer> modelIds) throws IOException, InterruptedException {
        for (Integer id: modelIds){
            String modelName = modelMapper.selectById(id);
            String code = modelMapper.selectCode(id);//模型简称
            String modelTrainFile = code + fileEnvIsotopeConfig.getModelTrainFile();
            String EnvConfig = fileEnvIsotopeConfig.getModelEnv()+"\\"+modelName;
            String trainFile = EnvConfig+fileEnvIsotopeConfig.getTrainFile();
            List<IsotopeTrain>isotopeTrainList = isotopeMapper.selectAll();
            CsvUtills.wCsvIso(trainFile,isotopeTrainList);
            ProcessBuilder processBuilder = new ProcessBuilder(fileEnvIsotopeConfig.getPythonEnv(), modelTrainFile);
            processBuilder.directory(new File(EnvConfig));
            Process process = processBuilder.start();
            int exitCode = process.waitFor();
            System.out.println("模型训练执行完成，退出码：" + exitCode);
        }
    }

    @Override
    public ResponseEntity<List<IsotopeRunVo>> testEle(List<Integer> modelIds, List<Integer> ids) throws IOException, InterruptedException {
        // 创建一个新的列表，只包含contents、prediction和modelName
        List<IsotopeRunVo> filteredList = new ArrayList<>();
        for (Integer modelId : modelIds) {
            String modelName = modelMapper.selectById(modelId);
            System.out.println(modelName);
            String code = modelMapper.selectCode(modelId);//模型简称
            String modelTestFile = code + fileEnvIsotopeConfig.getModelTestFile();
            System.out.println(modelTestFile);
            String EnvConfig = fileEnvIsotopeConfig.getModelEnv()+"\\"+modelName;
            String testFile = EnvConfig+fileEnvIsotopeConfig.getTestFile();
            List<IsotopeTest>isotopeTestList = isotopeMapper.selectByIds(ids);
            CsvUtills.wCsvIsoTest(testFile,isotopeTestList);

            ProcessBuilder processBuilder = new ProcessBuilder(fileEnvIsotopeConfig.getPythonEnv(), modelTestFile);
            processBuilder.directory(new File(EnvConfig));
            Process process = processBuilder.start();
            int exitCode = process.waitFor();
            System.out.println("模型预测执行完成，退出码：" + exitCode);

            //获取预测结果文件路径
            String preFile = EnvConfig + fileEnvIsotopeConfig.getPreFile();
            Path filePath = Paths.get(preFile);

            //检查文件是否存在
            if(!Files.exists(filePath)){
                throw new IOException("预测结果文件不存在");
            }

            //读取CSV文件并解析为ElementRunVo对象列表
            List<IsotopeRunVo> resultList = new ArrayList<>();
            try (FileReader reader = new FileReader(filePath.toFile())) {
                resultList = new CsvToBeanBuilder(reader)
                        .withType(IsotopeRunVo.class)
                        .build()
                        .parse();
            } catch (IOException e) {
                e.printStackTrace();
                throw new IOException("读取预测结果文件失败", e);
            }
            //将预测结果加入到resultList中
            for (IsotopeRunVo isotope : resultList) {
                IsotopeRunVo filteredIsotope = new IsotopeRunVo();
                filteredIsotope.setContents(isotope.getContents());
                int prediction = Integer.parseInt(isotope.getPrediction());
                String oresName3 = locMapper.selectOres3Name(prediction);
                filteredIsotope.setPrediction(oresName3);
                filteredIsotope.setModelName(modelMapper.selectById(modelId));
                filteredList.add(filteredIsotope);
            }
        }

        // 设置响应头信息等，返回包含过滤后ElementTest列表的ResponseEntity
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        return new ResponseEntity<>(filteredList, headers, HttpStatus.OK);
    }

    @Override
    public void addBatch(List<IsotopeAddDto> isotopeAddDtoList) {
        for(IsotopeAddDto isotopeAddDto: isotopeAddDtoList){
            add(isotopeAddDto);
        }
    }

    @Override
    public ResponseEntity<List<IsotopeBatchVo>> uploadFile(MultipartFile file) {
        try {
            List<IsotopeBatchVo> isotopeList = new ArrayList<>();

            String fileName = file.getOriginalFilename();

            // 判断文件类型，如果是 CSV 文件，使用 CSV 解析
            if (fileName.endsWith(".csv")) {
                Reader reader = new InputStreamReader(file.getInputStream(), StandardCharsets.UTF_8);
                CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT.withFirstRecordAsHeader());
                for (CSVRecord csvRecord : csvParser) {
                    IsotopeBatchVo elementBatchVo = IsotopeBatchVo.builder()
                            .contents(csvRecord.get("样品编号"))
                            .typeName(csvRecord.get("样品类别"))
                            .ores1Name(csvRecord.get("成矿带"))
                            .ores2Name(csvRecord.get("矿带"))
                            .ores3Name(csvRecord.get("矿点"))
                            .recName(csvRecord.get("识别状态"))
                            .a(csvRecord.get("δ34SvCDT"))
                            .se(csvRecord.get("SE"))
                            .originName(csvRecord.get("样品来源"))
                            .build();
                    isotopeList.add(elementBatchVo);
                }
                csvParser.close();
            }
            // 如果是 Excel 文件（.xlsx），使用 Apache POI 解析
            else if (fileName.endsWith(".xlsx") || fileName.endsWith(".xls")) {
                Workbook workbook = new XSSFWorkbook(file.getInputStream());  // 适用于 .xlsx 格式
                Sheet sheet = workbook.getSheetAt(0);  // 获取第一个 sheet

                for (Row row : sheet) {
                    // 跳过标题行
                    if (row.getRowNum() == 0) continue;

                    IsotopeBatchVo isotopeBatchVo = IsotopeBatchVo.builder()
                            .contents(row.getCell(0).getStringCellValue())  // 样品编号在第一列
                            .typeName(row.getCell(1).getStringCellValue())  // 样品类别在第二列
                            .a(String.valueOf(row.getCell(2).getNumericCellValue()))  // δ34SvCDT 在第三列
                            .se(String.valueOf(row.getCell(3).getNumericCellValue()))  //  SE 在第四列
                            .ores1Name(row.getCell(4).getStringCellValue())  // 成矿带在第五列
                            .ores2Name(row.getCell(5).getStringCellValue())  // 矿带在第六列
                            .ores3Name(row.getCell(6).getStringCellValue())  // 矿点在第七列
                            .recName(row.getCell(7).getStringCellValue())  // 识别状态在第八列
                            .originName(row.getCell(8).getStringCellValue())  // 样品来源在第九列
                            .build();
                    isotopeList.add(isotopeBatchVo);
                }
                workbook.close();
            }

            return ResponseEntity.ok(isotopeList);
        } catch (IOException e) {
            e.printStackTrace();
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
        }
    }
}
